package service

import (
	"context"
	"fmt"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/wrapperspb"
	"io"
	"log"
	"protol.com/ecommerce"
	"strings"
)

// 忽略变量值。用于类型检查，确保OrderManagementImpl实现了接口OrderManagementServer的所有方法
var _ ecommerce.OrderManagementServer = &OrderManagementImpl{}

var orders = make(map[string]ecommerce.Order)

type OrderManagementImpl struct {
	ecommerce.UnimplementedOrderManagementServer
}

func init() {
	orders["1"] = ecommerce.Order{
		Description: "订单",
	}
}

// Simple RPC
func (s *OrderManagementImpl) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*ecommerce.Order, error) {
	ord, exists := orders[orderId.Value]
	if exists {
		return &ord, status.New(codes.OK, "").Err()
	}

	return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId)
}

// 可以把stream看做客户端对象，不断向这个客户端对象中写入数据，返回nil或者err表示写入完成
func (s *OrderManagementImpl) SearchOrders(query *wrapperspb.StringValue, stream ecommerce.OrderManagement_SearchOrdersServer) error {
	for _, order := range orders {
		for _, str := range order.Items {
			if strings.Contains(str, query.Value) {
				err := stream.Send(&order)
				if err != nil {
					return fmt.Errorf("error send: %v", err)
				}
			}
		}
	}

	return nil
}

// 在这段程序中，我们对每一个 Recv 都进行了处理
// 当发现 io.EOF (流关闭) 后，表示客户端已经停止发送请求，需要将最终的响应结果发送给客户端，同时关闭正在另外一侧等待的 Recv
func (s *OrderManagementImpl) UpdateOrders(stream ecommerce.OrderManagement_UpdateOrdersServer) error {
	ordersStr := "Updated Order IDs : "
	for {
		order, err := stream.Recv()
		if err == io.EOF {
			// Finished reading the order stream.
			return stream.SendAndClose(
				&wrapperspb.StringValue{Value: "Orders processed " + ordersStr})
		}
		// Update order
		orders[order.Id] = *order

		log.Println("Order ID ", order.Id, ": Updated")
		ordersStr += order.Id + ", "
	}
}
